package com.elinkway.infinitemovies.download;

import com.elinkway.infinitemovies.application.MoviesApplication;
import com.elinkway.infinitemovies.bean.PostCloudErrorBean;
import com.elinkway.infinitemovies.dao.PreferencesManager;
import com.elinkway.infinitemovies.ui.activity.play.PlayerUtils;
import com.elinkway.infinitemovies.utils.CvcHelperManager;
import com.elinkway.infinitemovies.utils.LogUtils;
import com.elinkway.infinitemovies.utils.MoviesConstant;
import com.elinkway.infinitemovies.utils.MoviesUtils;
import com.elinkway.infinitemovies.utils.SharePreferenceManager;
import com.elinkway.infinitemovies.utils.StringUtil;
import com.leeco.pp.entity.CvcNormalTask;
import com.leeco.pp.entity.CvcTask;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.StatusLine;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.params.HttpConnectionParams;
import org.apache.http.params.HttpParams;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.RandomAccessFile;
import java.net.HttpURLConnection;

@SuppressWarnings("ALL")
public class CDNDownloadHandler implements DownloadHandler {
    public final static String TAG = "CDNDownloadHandler";
    private static final int ONE_SECONDS = 1000;
    private static final int MIN_SPEED = 100; //KB
    PostCloudErrorBean postCloudErrorBean;

    public static boolean isFinalState = false;
    @Override
    public int downloadFile(DownloadJob job) throws IOException {
        if (job.isCancelled() || job.getStatus() != DownloadJob.DOWNLOADING) { //当添加任务到线程池的瞬间迅速点击暂停 Cancell的bug
            return DOWNLOAD_FILE_ERROR;
        }
        final DownloadEntity downloadEntity = job.getEntity();
        boolean isSpeedLimit = false;
        boolean isNets = MoviesUtils.isNets(downloadEntity.getSite());
        boolean isLetv = MoviesUtils.isLetv(downloadEntity.getSite());
        int speed = 0;
        //only net disk limit speed
        if (isNets) {
            speed = PreferencesManager.getInstance().getSpeed(); //KB
            isSpeedLimit = (speed > 0);
            //Check weather web config speed too slow
            speed = Math.max(speed, MIN_SPEED);
        }

        String path = "";
        if (job.getStreamList() != null && job.getStreamList().size() > 1) {
            path = job.getDestination() + "/" + downloadEntity.getSaveName();
        } else {
            path = job.getDestination();
        }
        String fileName = "";
        if (job.getStreamList() != null && job.getStreamList().size() > 1) {
            fileName = job.getCurrentDownloadPiece() + ".mp4";
        } else {
            fileName = downloadEntity.getSaveName() + ".mp4";
        }

        new DownloadManager().deleteEmptyFile(path + "/" + downloadEntity.getSaveName());

        //构建下载目录
        try {
            File file = new File(path);
            if (!file.exists())
                file.mkdirs();
        } catch (Exception e) {
            e.printStackTrace();
            job.setExceptionType(DownloadJob.FILE_NOT_FOUND);
            return DOWNLOAD_FILE_ERROR;
        }

        if (isNets && SharePreferenceManager.getVaule(MoviesApplication.getInstance(), downloadEntity.getSite())) {

            //P2P下载
            CvcHelperManager.getInstance().setDownloadJob(job);
            CvcNormalTask mTask = (CvcNormalTask) job.getmCvcTask();
            if (mTask == null) {
                mTask = new CvcNormalTask(downloadEntity.getDownloadUrl(), fileName, downloadEntity.getgSize(), downloadEntity.getMd5(), path);
                job.setmCvcTask(mTask);
                CvcHelperManager.getInstance().startDownload(mTask);
            } else if (mTask.getState() == CvcTask.TaskState.PAUSED || mTask.getState() == CvcTask.TaskState.IDLE) {
                CvcHelperManager.getInstance().resumeDownload(mTask);
            }
            job.setProgress(job.initProgress());
            if (job.getProgress() == 100) {
                return DOWNLOAD_SUCCESS;
            }

            job.setTotalSize(mTask.getFileSize());
            job.setDownloadedSize(mTask.getDownloadBytes());
            job.setRate();
            while(!isFinalState) {
                continue;
            }

            LogUtils.d(TAG, "----------current downloadTask's download state is:" + mTask.getState());
            switch (mTask.getState()) {
                case SUCCESS:
                    LogUtils.e(TAG, "-------P2P DOWNLOAD SUCCESS");
                    return DOWNLOAD_SUCCESS;
                case FAILED:
                    LogUtils.e(TAG, "-------P2P DOWNLOAD FAIL");
                    return DOWNLOAD_FILE_ERROR;
                default:
                    return DOWNLOAD_FILE_ERROR;
            }
        }

        HttpParams params = new BasicHttpParams();
        HttpConnectionParams.setConnectionTimeout(params,
                5 * 1000);
        HttpConnectionParams.setSoTimeout(params, 5 * 1000);
        HttpConnectionParams.setSocketBufferSize(params, 8192 * 5);
        HttpGet httpGet = new HttpGet(downloadEntity.getDownloadUrl());

        File file = new File(path, fileName);
        LogUtils.e(TAG, "mp4 down path is " + file.getAbsolutePath());
        LogUtils.e(TAG, "!!!!!!!!!!!!!!!! waiting mp4 down result !!!!!!!!!!!!!!!!!!!");
        RandomAccessFile randomFile = null;
        try {
            randomFile = new RandomAccessFile(file, "rw");
            LogUtils.d(TAG, "---------开始下载时候通过randomFile 获取文件的大小" + randomFile.length() + "来设置DownloadedSize-----------");
            job.setDownloadedSize(randomFile.length());
        } catch (Exception e) {
            e.printStackTrace();
            if (randomFile != null)
                randomFile.close();
            job.setExceptionType(DownloadJob.FILE_NOT_FOUND);
            LogUtils.d(TAG,"---------catch Exception is:" + e.toString() + "and current error job is:" + job.getEntity().getDisplayName());
            return DOWNLOAD_FILE_ERROR;
        }
        LogUtils.d(TAG, "--------downloadSize is:" + job.getDownloadedSize() + ",,,,totleSize is:" + job.getTotalSize() + "and progress is:" + job.getProgress() + "--------");
        job.setProgress(job.initProgress());
        if (job.getProgress() == 100) {
            if (randomFile != null)
                randomFile.close();
            return DOWNLOAD_SUCCESS;
        }

        /**
         * 断点续传
         */
        httpGet.addHeader("Range",
                "bytes=" + randomFile.length() + "-");
        String userAgent = job.getmUser_agent();
        if (!StringUtil.isEmpty(userAgent)) {
            httpGet.addHeader("User-Agent", userAgent);
            LogUtils.e(TAG, "##############mp4 userAgent is " + userAgent);
        }
        HttpResponse response = null;
        try {
            response = new DefaultHttpClient(params).execute(httpGet); //出错
        } catch (Exception e) {

            if (randomFile != null)
                randomFile.close();

            LogUtils.e(TAG,"---------DOWNLOAD_URL_INVALID，and current error job is:" + job.getEntity().getDisplayName());
            return DOWNLOAD_FILE_ERROR;
        }

        HttpEntity entity = response.getEntity();
        StatusLine statusLine = response.getStatusLine();
        final int respCode = statusLine.getStatusCode();
        if (HttpURLConnection.HTTP_PARTIAL != respCode) {  //判断是否支持断点续传
            if (randomFile != null)
                randomFile.close();

            LogUtils.e(TAG,"---------DOWNLOAD_URL_INVALID，and current error job is:" + job.getEntity().getDisplayName());
            return DOWNLOAD_URL_INVALID;
        }
        //上报
        if (job.getAutoSnifferRetry()) {
            job.addReportState(PlayerUtils.M401);
        } else {
            job.addReportState(PlayerUtils.M411);
        }
        //
        long length = entity.getContentLength();
        LogUtils.d(TAG, "---------开始下载时候entity.getContentLength()获取的大小：：：" + length + "-------");
        long totleSizeFromServer = new Double(job.getTotleSizeFromServer()).longValue();
        long totalSize = 0;
        if (totleSizeFromServer > 0) {
            totalSize = totleSizeFromServer;
        } else {
            totalSize = randomFile.length() + length;
        }
        LogUtils.d(TAG, "---------设置的totleSize的大小：：：" + totalSize + "-------");
        job.setTotalSize(totalSize);

        InputStream in = entity.getContent();
        if (in == null) {
            if (randomFile != null)
                randomFile.close();
            LogUtils.e(TAG,"---------DOWNLOAD_FILE_ERROR111111111--------and current error job is:" + job.getEntity().getDisplayName());
            return DOWNLOAD_FILE_ERROR;
        }
        randomFile.seek(randomFile.length());

        byte[] buffer = new byte[1024];
        int speedLimit = 0;
        if (isSpeedLimit) {
            //int max 2048M
            speedLimit = speed * 1024;
            LogUtils.d(TAG, "speed:" + speed + "KB speedLimit:" + speedLimit + "B");
        }
        int readLength = 0;
        int bufLength = 0;
        try {
            long initTime = System.currentTimeMillis();
            if ((bufLength = in.read(buffer)) != -1 && !job.isCancelled()) {
                //speed limit
                readLength += bufLength;
                if (isSpeedLimit && readLength >= speedLimit) {
                    int diff = (int) (System.currentTimeMillis() - initTime);
                    if (diff < ONE_SECONDS) {
                        Thread.sleep(ONE_SECONDS - diff);
                    }
                    initTime = System.currentTimeMillis();
                    readLength = 0;
                }

                job.reportDownloadState(MoviesConstant.DOWNLOAD_SUCCESS_STATE);
                randomFile.write(buffer, 0, bufLength);
                job.setDownloadedSize(randomFile.length());
                job.setRate();
            } else {
                if (!job.isCancelled()) {
                    job.reportDownloadState(MoviesConstant.DOWNLOAD_FAIL_STATE);
                }
            }
            while ((bufLength = in.read(buffer)) != -1 && !job.isCancelled()) {//点击暂停可能触发这里的error，然后被catch
                //speed limit
                readLength += bufLength;
                if (isSpeedLimit && readLength >= speedLimit) {
                    int diff = (int) (System.currentTimeMillis() - initTime);
                    if (diff < ONE_SECONDS) {
                        Thread.sleep(ONE_SECONDS - diff);
                    }
                    initTime = System.currentTimeMillis();
                    readLength = 0;
                }

                randomFile.write(buffer, 0, bufLength);
                /**
                 * 更新进度条
                 */
                job.setDownloadedSize(randomFile.length());
                job.setRate();
            }
        } catch (Exception e) {
            in.close(); //TODO 可能存在bug，直接异常没catch
            randomFile.close();
            httpGet.abort(); //终止
            if (e.toString().contains("No space left on device")) {
                job.setExceptionType(DownloadJob.SD_SPACE_FULL);
            } else if (e.toString().contains("java.io.FileNotFoundException")
                    || e.toString().contains("java.io.IOException: write failed: EIO (I/O error)")) {
                job.setExceptionType(DownloadJob.NO_SD);// 没有sdcard，或者sdcard拔出或者存储器模式
            }
            e.printStackTrace();
            LogUtils.d(TAG,"---------DOWNLOAD_FILE_ERROR2222222222，，and current error job is:" + job.getEntity().getDisplayName() + "catch Exception" + e.toString());
            LogUtils.e(TAG,"---------DOWNLOAD_FILE_ERROR2222222222--------job.getProgress() is" + job.getProgress() + "and current error job is:" + job.getEntity().getDisplayName());
            return DOWNLOAD_FILE_ERROR;
        }
        randomFile.close();
        httpGet.abort();
        if (job.getDownloadedSize() < job.getTotalSize()) { //解决有时没下载完就返回true，显示下载完成
            LogUtils.e(TAG,"---------DOWNLOAD_FILE_ERROR，，and current error job is:" + job.getEntity().getDisplayName() + "--------");
            return DOWNLOAD_FILE_ERROR;
        }
        LogUtils.e(TAG,"---------正常下载完成----------");
        return DOWNLOAD_SUCCESS;
    }

    @Override
    public void onCompleted () {
    }

    @Override
    public void onFailure () {
    }

    @Override
    public void onPause (DownloadJob job){
        if (job == null) {
            return;
        }
        DownloadEntity currentEntity = job.getEntity();
        if (currentEntity == null) {
            return;
        }
        if (MoviesUtils.isNets(currentEntity.getSite())) {
            CvcHelperManager.getInstance().pauseDownload(job.getmCvcTask());
        }
    }

    @Override
    public void onStart () {

    }

}
